//
//  AsmanLiteManager.swift
//  vr_web
//
//  Created by 李旭峰 on 2020/7/13.
//

import Foundation
import UIKit
import RxSwift
import RxCocoa
import FCUUID
import TXLiteAVSDK_TRTC

typealias TXLiteSuccess = ()->Void
typealias TXLiteFail = (_ errorCode: Int)->Void

typealias RtcEnterRoomCallBack = (_ success:Bool,_ error:Error?,_ errorCode:Int?)->Void
typealias RtcExitRoomCallBack = (_ success:Bool,_ error:Error?,_ errorCode:Int?)->Void
typealias LoadRtcAuthInfoAction = (_ success:Bool,_ params:[String:Any],_ error:Error?)-> Void
typealias LoadRtcCallStatus = (_ success:Bool,_ error:Error?) -> Void
typealias ResponseRtcLogAction = (_ success:Bool,_ error:Error?) -> Void
// 收到socket或者点击推送
// 判断是否正在处理 -> 是 直接返回繁忙
// -> 否 ->
// -> 否 ->
class TXLiteAction {
    let requestCode:String
    var success: TXLiteSuccess?
    var failed: TXLiteFail?
    init(success:TXLiteSuccess? = nil,failed:TXLiteFail? = nil) {
        self.requestCode = FCUUID.uuid()!.uppercased()
        self.success = success
        self.failed = failed
    }
}
@objc protocol AsmanLiteDelegate {
    func onUserEnterRoom()
    func onUserLeaveRoom()
    func onRemoteUserEnterRoom(_ userId: String)
    func onRemoteUserLeaveRoom(_ userId: String, reason: Int)
}
class AsmanLiteManager: NSObject {
    private struct RtcLogParams {
        var type:String = ""
        var roomId:String = ""
        var userId:String = ""
    }
    
    var loadRtcAuthIntoActions:[String:LoadRtcAuthInfoAction] = [:]
    var loadRtcCallStatusActions:[String:LoadRtcCallStatus] = [:]
    private var rtcLogActions:[String:ResponseRtcLogAction] = [:]
    private var rtcLogParamsMap:[String:RtcLogParams] = [:]
    @objc enum RtcStatus:Int {
        case kInvalid = 1
        case kDidInit
        case kDidEnter
        case kWarting
        case kHangUp
        case kAnswer
    }
    /// 单例属性
    static let `default`: AsmanLiteManager = AsmanLiteManager()
    var currentLiteAction:TXLiteAction?
    let trtcCloud:TRTCCloud = TRTCCloud.sharedInstance()
    weak var delegate:AsmanLiteDelegate?
    var isWartEnterRoom:Bool = false
    /// 是否在房间中
    /// 调用enterRoom开始，则表示已经进入房间，值将置为 true
    /// 初始状态，或 调用 exitRoom 并收到 onExitRoom 后，才算退出房间，值将置为 false
    private(set) var didEnterRoom:Bool = false
    private(set) var didJoinRoom:Bool = false
    private var enterRoomCallBack:RtcEnterRoomCallBack?
    private var exitRoomCallBack:RtcExitRoomCallBack?
    /// 用户已离开
    private(set) var isSomeoneLeave:Bool = false
    /// 是否有用户加入房间
    private(set) var isUserJoinRoom:Bool = false
    /// 加入者的ID
    private(set) var otherUserId:String?
    private var hangUpRoom:[Int32] = []
    func didHangUp(for roomId:Int32) -> Bool {
        return false
    }
    
    
    var roomId:UInt32?
    var schemeId:String?
    var rtcStatus:RtcStatus = .kInvalid
    /// 正在处理 RTC 流程
    var isRtcWorking:Bool = false
    
    var isJoinAppBecomeActive:Bool = true
    var isInitRtc:Bool = false
    
    func syncLoadRtcCallStatus(roomId:String,didCompleted:@escaping LoadRtcCallStatus){
        let request = GetRtcCallStatusRequest(self)
        self.loadRtcCallStatusActions[request.szRequestId] = didCompleted
        request.loadData()
    }
}

extension AsmanLiteManager {
    
    func initRtcRoom(withRoomId roomId:UInt32,schemeId:String,params:[String:Any],callBack: RtcEnterRoomCallBack?){// 已经在房间中，提示繁忙并返回
        if self.rtcStatus != .kInvalid {
            callBack?(false,nil,-10000)
            return
        }
        self.roomId = roomId
        self.schemeId = schemeId
        self.rtcStatus = .kDidInit
        self.syncLoadRtcCallStatus(roomId: String(roomId)) { (success, error) in
            callBack?(success,nil,success ? nil : -10000)
        }
    }
    func initRtcRoom2(withRoomId roomId:UInt32,schemeId:String,params:[String:Any],callBack: RtcEnterRoomCallBack?){
        if self.rtcStatus != .kInvalid {
            callBack?(false,nil,-10000)
            return
        }
        self.roomId = roomId
        self.schemeId = schemeId
        self.rtcStatus = .kDidInit
        callBack?(true,nil, nil)
    }
    func deinitRtcRoom(){
        self.rtcStatus = .kInvalid
        self.roomId = nil
        self.schemeId = nil
        self.isSomeoneLeave = false
        self.isUserJoinRoom = false
        self.otherUserId = nil
    }
    // 创建房间
    // 加入房间
    /// 加入房间
    /// - Parameters:
    ///   - sdkAppId: sdkAppId
    ///   - userSig: 加密
    ///   - userId: 用户ID
    ///   - roomId: 房间ID
    func enterRoom(sdkAppId:UInt32,userSig:String,userId:String,roomId:UInt32,callBack: RtcEnterRoomCallBack?) {
        self.didEnterRoom = true
        self.enterRoomCallBack = callBack
        let params = TRTCParams.init()
        params.sdkAppId = sdkAppId
        params.userId   = userId
        params.roomId   = roomId
        params.userSig  = userSig
        params.privateMapKey = ""
        
        let trtc:TRTCCloud = TRTCCloud.sharedInstance()
        
        trtc.setDefaultStreamRecvMode(true, video: false)
        
        TRTCCloud.sharedInstance().delegate = self
        trtcCloud.enterRoom(params, appScene: .videoCall)
        TRTCCloud.sharedInstance()?.startLocalAudio()
        TRTCCloud.sharedInstance()?.enableAudioVolumeEvaluation(300)
    }
    
    // 离开房间
    // 调用退房后请等待 onExitRoom 事件回调
    func exitRoom(withCallBack callBack:RtcExitRoomCallBack?){
        dPrintLog("RTC", "exit room : \(roomId)")
        TRTCCloud.sharedInstance()?.stopLocalAudio()
        TRTCCloud.sharedInstance()?.stopLocalPreview()
        self.exitRoomCallBack = callBack
        if !self.didJoinRoom {
            self.didEnterRoom = false
            self.didJoinRoom = false
            self.exitRoomCallBack?(true,nil,nil)
            self.exitRoomCallBack = nil
        }else {
            self.trtcCloud.exitRoom()
        }
    }
}
extension AsmanLiteManager : TRTCCloudDelegate {
    /// 用户加入房间
    func onEnterRoom(_ result: Int) {
        dPrintLog("RTC", "用户加入房间是否成功：result = \(result)")
        if result > 0 {
            self.rtcStatus = .kDidEnter
            self.didJoinRoom = true
            self.currentLiteAction?.success?()
            self.currentLiteAction = nil
            self.enterRoomCallBack?(true,nil,nil)
            self.enterRoomCallBack = nil
            self.delegate?.onUserEnterRoom()
        } else {
            self.currentLiteAction?.failed?(result)
            self.exitRoom(withCallBack:nil)
            self.enterRoomCallBack?(false,nil,result)
            self.enterRoomCallBack = nil
            self.delegate?.onUserLeaveRoom()
        }
    }
    /// 用户离开房间
    func onExitRoom(_ reason: Int) {
        dPrintLog("RTC", "用户离开房间是否成功：result = \(reason)")
        self.didEnterRoom = false
        self.didJoinRoom = false
        TRTCCloud.sharedInstance().delegate = nil
        self.exitRoomCallBack?(true,nil,reason)
        self.delegate?.onUserLeaveRoom()
    }
    func onError(_ errCode: TXLiteAVError, errMsg: String?, extInfo: [AnyHashable : Any]?) {
        
    }
    /// 有人加入房间
    func onRemoteUserEnterRoom(_ userId: String) {
        dPrintLog("RTC", "有人加入房间 - userId : \(userId)")
        self.isUserJoinRoom = true
        self.otherUserId = userId
        self.delegate?.onRemoteUserEnterRoom(userId)
    }
    /// 有人离开房间
    func onRemoteUserLeaveRoom(_ userId: String, reason: Int) {
        dPrintLog("RTC", "有人离开房间 - userId : \(userId)，reason : \(reason)")
        self.isSomeoneLeave = true
        self.isUserJoinRoom = false
        self.delegate?.onRemoteUserLeaveRoom(userId, reason: reason)
    }
}

extension AsmanLiteManager : RequestCallBack, RequestDataReformer, RequestParamSource, RequestBodySource, RequestHeaderSource{
    func requestBaseUrl(_ request: BaseRequest) -> String? {
        return nil
    }
    
    func requestHeader(_ request: BaseRequest) -> [String : Any]? {
        return nil
    }
    
    func requestDidSucess(_ request: BaseRequest) {}
    
    func requestDidFail(_ request: BaseRequest) {
        if request is GetRtcAuthInfoRequest {
            let action = self.loadRtcAuthIntoActions[request.szRequestId]
            self.loadRtcAuthIntoActions[request.szRequestId] = nil
            let error = NSError(domain: "AsmanError", code: -10000, userInfo: ["Message":request.errorMsg])
            action?(false,[:],error)
        }
        if request is GetRtcCallStatusRequest {
            let action = self.loadRtcCallStatusActions[request.szRequestId]
            self.loadRtcCallStatusActions[request.szRequestId] = nil
            let error = NSError(domain: "AsmanError", code: -10000, userInfo: ["Message":request.errorMsg])
            action?(false,error)
        }
        if request is RtcLogRequest {
            let action = self.rtcLogActions[request.szRequestId]
            self.rtcLogActions[request.szRequestId] = nil
            self.rtcLogParamsMap[request.szRequestId] = nil
            let error = NSError(domain: "AsmanError", code: -10000, userInfo: ["Message":request.errorMsg])
            action?(false,error)
        }
    }
    
    func reform(_ request: BaseRequest, _ data: [String : Any]?) {
        if request is GetRtcAuthInfoRequest {
            let action = self.loadRtcAuthIntoActions[request.szRequestId]
            self.loadRtcAuthIntoActions[request.szRequestId] = nil
            guard let `data` = data?["result"] as? [String:Any] else {
                let error = NSError(domain: "AsmanError", code: -10000, userInfo: ["Message":"数据异常"])
                action?(false,[:],error)
                return
            }
            guard let _ = String.SwitchToString(data["sdkAppId"]),let _ = String.SwitchToString(data["userSig"]) else {
                let error = NSError(domain: "AsmanError", code: -10000, userInfo: ["Message":"数据异常"])
                action?(false,[:],error)
                return
            }
            action?(true,data,nil)
        }
        if request is GetRtcCallStatusRequest {
            let action = self.loadRtcCallStatusActions[request.szRequestId]
            self.loadRtcCallStatusActions[request.szRequestId] = nil
            guard let result = String.SwitchToString(data?["result"])?.decimal.boolValue else {
                let error = NSError(domain: "AsmanError", code: -10000, userInfo: ["Message":"接听超时"])
                action?(false,error)
                return
            }
            action?(result,result ? nil : NSError(domain: "AsmanError", code: -10000, userInfo: ["Message":"接听超时"]))
        }
        if request is RtcLogRequest {
            let action = self.rtcLogActions[request.szRequestId]
            self.rtcLogActions[request.szRequestId] = nil
            self.rtcLogParamsMap[request.szRequestId] = nil
            action?(true,nil)
        }
    }
    
    func requestParams(_ request: BaseRequest) -> [String : Any]? {
        var params:[String:Any] = [:]
        if request is GetRtcCallStatusRequest {
            params["roomId"] = self.roomId
        }
        if request is GetRtcAuthInfoRequest {
            params["schemeId"] = self.schemeId
        }
        return params
    }
    
    func requestBody(_ request: BaseRequest) -> Any? {
        var body:[String:Any] = [:]
        if request is RtcLogRequest,let params = self.rtcLogParamsMap[request.szRequestId] {
            body["type"] = params.type
            body["roomId"] = params.roomId
            body["userId"] = params.userId
        }
        return body
    }
    
}
